package main

import (
	"fmt"
	"math"
)

func main() {
	/*
		语法格式一：
			//安全类型的断言
			<目标类型的值>,<布尔参数> := <表达式>.(目标类型)
			//非安全类型的断言
			<目标类型的值> := <表达式>.(目标类型)

		语法格式二：switch
		switch instance := 接口对象.(type){
			case 实际类型1:
					...
			case 实际类型2:
					...
			...
		}
	*/
	var t1 = Triangle{3, 4, 5}
	fmt.Println(t1.a, t1.b, t1.c)
	fmt.Println(t1.peri())
	fmt.Println(t1.area())

	var c1 = Circle1{3}
	fmt.Println(c1.radius)
	fmt.Println(c1.peri())
	fmt.Println(c1.area())

	var s1 Shape
	s1 = t1
	fmt.Println(s1.peri())
	fmt.Println(s1.area())

	var s2 Shape
	s2 = c1
	fmt.Println(s2.area())
	fmt.Println(s2.peri())

	var c2 = &Circle1{5}
	fmt.Printf("c2:%T,%p \n", c2, &c2)

	testShape(t1)
	testShape(c1)
	testShape(s1)

	getType(t1)
	getType(c1)
	getType(s1)
	getType(c2)

	getType2(t1)
	getType2(c1)
	getType2(s1)
	getType2(c2)

}

//switch 获取类型
func getType2(s Shape) {
	switch ins := s.(type) {
	case Triangle:
		{
			fmt.Println("switch 是三角形，", ins.a, ins.b, ins.c)
		}
	case Circle1:
		{
			fmt.Println("switch 是圆形，", ins.radius)
		}
	case *Circle1:
		{
			fmt.Println("switch 是圆形结构体指针类型：", ins.radius)
		}
	}
}

//断言获取类型
func getType(s Shape) {
	if ins, ok := s.(Triangle); ok {
		fmt.Println("是三角形，三边是：", ins.a, ins.b, ins.c)
	} else if ins, ok := s.(Circle1); ok {
		fmt.Println("是圆形，半径是：", ins.radius)
	} else if ins, ok := s.(*Circle1); ok {
		fmt.Println("是圆形指针类型", ins.radius)
	} else {
		fmt.Println("类型不知道是啥")
	}
}

// 定义一个接口
type Shape interface {
	peri() float64 //周长
	area() float64 //面积
}

//定义实现类型：三角形
type Triangle struct {
	a, b, c float64
}

func testShape(s Shape) {
	fmt.Printf("周长：%.2f,面积：%.2f\n", s.peri(), s.area())
}

func (t Triangle) peri() float64 {
	return t.a + t.b + t.c
}

func (t Triangle) area() float64 {
	p := t.peri() / 2
	s := math.Sqrt(p * (p - t.a) * (p - t.b) * (p - t.c))
	return s
}

type Circle1 struct {
	radius float64
}

func (c Circle1) peri() float64 {
	return c.radius * 2 * math.Pi
}

func (c Circle1) area() float64 {
	return math.Pi * c.radius * c.radius
}
